import { Injectable, Injector, Optional } from '@angular/core';
import {
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
  HttpResponse,
  HttpSentEvent,
  HttpHeaderResponse,
  HttpProgressEvent,
  HttpUserEvent,
  HttpErrorResponse,
  HttpEvent
} from '@angular/common/http';

import { Observable, Observer } from 'rxjs';
import { AuthConfig } from '../../config/auth.config';
import { IToken } from '../auth.interface';
import { I18NService } from '../../i18n/i18n.service';

/**
 * 请求拦截器
 */
@Injectable()
export abstract class BaseInterceptor implements HttpInterceptor {

  constructor(
    @Optional() protected injector: Injector,
    private i18nService: I18NService
  ) { }

  protected model: IToken;

  abstract isAuth(options: AuthConfig): boolean;

  abstract setReq(req: HttpRequest<any>, options: AuthConfig): HttpRequest<any>;

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<| HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
    const options = Object.assign(new AuthConfig(), this.injector.get(AuthConfig, null));
    if (options.ignores) {
      for (const item of options.ignores as RegExp[]) {
        if (item.test(req.url)) {
          return next.handle(req);
        }
      }
    }

    if (this.isAuth(options)) {
      req = this.setReq(req, options);
    } else {
      return new Observable((observer: Observer<HttpEvent<any>>) => {
        const res = new HttpErrorResponse({
          error: this.i18nService.translate('error.auth'),
          status: 401,
          statusText: 'error',
          url: req.url
        });
        observer.error(res);
      });
    }
    return next.handle(req);
  }
}
